"""
系统监控数据存储服务
"""
import psutil
import time
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional
from sqlalchemy.orm import Session
from sqlalchemy import desc, func

from core.database import get_db
from models.database import SystemMetrics
from core.config import get_settings
from core.logger import get_logger

logger = get_logger(__name__)
settings = get_settings()


class MetricsStorageService:
    """系统监控数据存储服务"""
    
    @staticmethod
    def save_metrics_to_db(metrics_data: Dict[str, Any]) -> bool:
        """保存监控数据到数据库"""
        try:
            db = next(get_db())
            # 创建监控数据记录
            metrics_record = SystemMetrics(
                cpu_percent=metrics_data.get('cpu_percent', 0),
                memory_percent=metrics_data.get('memory_percent', 0),
                memory_used=metrics_data.get('memory_used', 0),
                memory_total=metrics_data.get('memory_total', 0),
                disk_percent=metrics_data.get('disk_percent', 0),
                disk_used=metrics_data.get('disk_used', 0),
                disk_total=metrics_data.get('disk_total', 0),
                load_average=metrics_data.get('load_average', 0),
                uptime=metrics_data.get('uptime', 0),
                network_sent=metrics_data.get('network_sent', 0),
                network_recv=metrics_data.get('network_recv', 0),
                process_count=metrics_data.get('process_count', 0),
                thread_count=metrics_data.get('thread_count', 0),
                status=metrics_data.get('status', 'normal'),
                timestamp=datetime.now()
            )
            
            db.add(metrics_record)
            db.commit()
            logger.debug(f"监控数据已保存到数据库: {metrics_record.id}")
            return True
        except Exception as e:
            logger.error(f"保存监控数据到数据库失败: {e}")
            raise e
    
    @staticmethod
    def get_metrics_history(
        hours: int = 24,
        limit: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """获取历史监控数据"""
        try:
            db = next(get_db())
            
            # 计算时间范围
            start_time = datetime.now() - timedelta(hours=hours)
            
            # 构建查询
            query = db.query(SystemMetrics).filter(
                SystemMetrics.timestamp >= start_time
            ).order_by(desc(SystemMetrics.timestamp))
            
            if limit:
                query = query.limit(limit)
            
            metrics = query.all()
            
            # 转换为字典列表
            return [
                {
                    'id': m.id,
                    'cpu_percent': m.cpu_percent,
                    'memory_percent': m.memory_percent,
                    'memory_used': m.memory_used,
                    'memory_total': m.memory_total,
                    'disk_percent': m.disk_percent,
                    'disk_used': m.disk_used,
                    'disk_total': m.disk_total,
                    'load_average': m.load_average,
                    'uptime': m.uptime,
                    'network_sent': m.network_sent,
                    'network_recv': m.network_recv,
                    'process_count': m.process_count,
                    'thread_count': m.thread_count,
                    'status': m.status,
                    'timestamp': m.timestamp.isoformat()
                }
                for m in metrics
            ]
            
        except Exception as e:
            logger.error(f"获取历史监控数据失败: {e}")
            return []
    
    @staticmethod
    def get_metrics_summary(hours: int = 24) -> Dict[str, Any]:
        """获取监控数据统计摘要"""
        try:
            db = next(get_db())
            
            # 计算时间范围
            start_time = datetime.now() - timedelta(hours=hours)
            
            # 获取统计数据
            summary = db.query(
                func.avg(SystemMetrics.cpu_percent).label('avg_cpu'),
                func.max(SystemMetrics.cpu_percent).label('max_cpu'),
                func.min(SystemMetrics.cpu_percent).label('min_cpu'),
                func.avg(SystemMetrics.memory_percent).label('avg_memory'),
                func.max(SystemMetrics.memory_percent).label('max_memory'),
                func.min(SystemMetrics.memory_percent).label('min_memory'),
                func.avg(SystemMetrics.disk_percent).label('avg_disk'),
                func.max(SystemMetrics.disk_percent).label('max_disk'),
                func.min(SystemMetrics.disk_percent).label('min_disk'),
                func.count(SystemMetrics.id).label('total_records')
            ).filter(
                SystemMetrics.timestamp >= start_time
            ).first()
            
            if summary:
                return {
                    'avg_cpu': round(summary.avg_cpu or 0, 2),
                    'max_cpu': round(summary.max_cpu or 0, 2),
                    'min_cpu': round(summary.min_cpu or 0, 2),
                    'avg_memory': round(summary.avg_memory or 0, 2),
                    'max_memory': round(summary.max_memory or 0, 2),
                    'min_memory': round(summary.min_memory or 0, 2),
                    'avg_disk': round(summary.avg_disk or 0, 2),
                    'max_disk': round(summary.max_disk or 0, 2),
                    'min_disk': round(summary.min_disk or 0, 2),
                    'total_records': summary.total_records or 0,
                    'time_range_hours': hours
                }
            
            return {}
            
        except Exception as e:
            logger.error(f"获取监控数据统计摘要失败: {e}")
            return {}
    
    @staticmethod
    def cleanup_old_metrics(days: int = None) -> int:
        """清理旧的监控数据"""
        if days is None:
            days = settings.metrics_retention_days
        
        try:
            db = next(get_db())
            
            # 计算截止时间
            cutoff_time = datetime.now() - timedelta(days=days)
            
            # 删除旧数据
            deleted = db.query(SystemMetrics).filter(
                SystemMetrics.timestamp < cutoff_time
            ).delete()
            
            db.commit()
            
            logger.info(f"已清理 {deleted} 条 {days} 天前的监控数据")
            return deleted
            
        except Exception as e:
            logger.error(f"清理监控数据失败: {e}")
            return 0
    
    @staticmethod
    def get_latest_metrics() -> Optional[Dict[str, Any]]:
        """获取最新的监控数据"""
        try:
            db = next(get_db())
            
            latest = db.query(SystemMetrics).order_by(
                desc(SystemMetrics.timestamp)
            ).first()
            
            if latest:
                return {
                    'id': latest.id,
                    'cpu_percent': latest.cpu_percent,
                    'memory_percent': latest.memory_percent,
                    'memory_used': latest.memory_used,
                    'memory_total': latest.memory_total,
                    'disk_percent': latest.disk_percent,
                    'disk_used': latest.disk_used,
                    'disk_total': latest.disk_total,
                    'load_average': latest.load_average,
                    'uptime': latest.uptime,
                    'network_sent': latest.network_sent,
                    'network_recv': latest.network_recv,
                    'process_count': latest.process_count,
                    'thread_count': latest.thread_count,
                    'status': latest.status,
                    'timestamp': latest.timestamp.isoformat()
                }
            
            return None
            
        except Exception as e:
            logger.error(f"获取最新监控数据失败: {e}")
            return None
    
    @staticmethod
    def is_metrics_enabled() -> bool:
        """检查是否启用了监控数据保存"""
        return settings.save_metrics_to_db
    
    @staticmethod
    def get_metrics_config() -> Dict[str, Any]:
        """获取监控配置信息"""
        return {
            'save_metrics_to_db': settings.save_metrics_to_db,
            'metrics_retention_days': settings.metrics_retention_days,
            'metrics_collection_interval': settings.metrics_collection_interval,
            'enable_system_monitoring': settings.enable_system_monitoring
        }